package com.google.gwt.user.client.ui;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;

public class CustomPushButton extends PushButton {

    public CustomPushButton() {
		super();
		setWorkAround();
	}

	private void setWorkAround() {
        addMouseDownHandler(new MouseDownHandler() {
            @Override
            public void onMouseDown(final MouseDownEvent event) {
                doWorkAround(event);
            }
        });
	}

	public CustomPushButton(Image upImage, ClickHandler handler) {
		super(upImage, handler);
		setWorkAround();
	}

	public CustomPushButton(Image upImage, Image downImage, ClickHandler handler) {
		super(upImage, downImage, handler);
		setWorkAround();
	}

	public CustomPushButton(Image upImage, Image downImage) {
		super(upImage, downImage);
		setWorkAround();
	}

	public CustomPushButton(Image upImage) {
		super(upImage);
		setWorkAround();
	}

	public CustomPushButton(String upText, ClickHandler handler) {
		super(upText, handler);
		setWorkAround();
	}

	public CustomPushButton(String upText, String downText, ClickHandler handler) {
		super(upText, downText, handler);
		setWorkAround();
	}

	public CustomPushButton(String upText, String downText) {
		super(upText, downText);
		setWorkAround();
	}

	public CustomPushButton(String upText) {
		super(upText);
		setWorkAround();
	}

	private void doWorkAround(final MouseDownEvent event) {
        if (!CustomPushButton.this.isEnabled()) {
            // Per PushButton code in GWT 2.5.1, there is no hover attribute if the button is
            // actually disabled, so there is no reason to create/dispatch the event.
            return;
        }

        final int x0 = CustomPushButton.this.getAbsoluteLeft();
        final int x1 = x0 + CustomPushButton.this.getOffsetWidth();
        final int y0 = CustomPushButton.this.getAbsoluteTop();
        final int y1 = y0 + CustomPushButton.this.getOffsetHeight();

        final int x = event.getClientX();
        final int y = event.getClientY();

        // Only create and dispatch the mouse over event if the mouse was released
        // over the button. The other cases are handled properly.
        if (x >= x0 && x <= x1 && y >= y0 && y <= y1) {
            // Create a mouse over event using the mouse up event data, then dispatch
            // it to programmatically force a 'mouse over' event of the button.
            final NativeEvent mouseOverEvent = Document.get().createMouseOverEvent(0,
                event.getScreenX(),
                event.getScreenY(),
                event.getClientX(),
                event.getClientY(),
                event.isControlKeyDown(),
                event.isAltKeyDown(),
                event.isShiftKeyDown(),
                event.isMetaKeyDown(),
                event.getNativeButton(),
                null);
            CustomPushButton.this.getElement().dispatchEvent(mouseOverEvent);
        }
    }
}